package org.sidora.core;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.query.Predicate;
import org.sidora.core.util.AbstractFactory;
import org.sidora.core.util.AbstractInventory;
import org.sidora.core.util.OCProvider;
import org.sidora.core.util.ParameterCollector;

public class Assignment implements Comparable{
    private String idAssignment;
    private String description;
    
    //private Site site;
    private Action action;
    
    private TreeSet <User> team = new TreeSet<User>();
    private TreeSet <Zone> zones= new TreeSet<Zone>();;
    
    private Assignment(){    }
    public Action getAction() {
        return action;
    }
    public void setAction(Action action) {
        this.action = action;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getIdAssignment() {
        return idAssignment;
    }
    public void setIdAssignment(String idAssignment) {
        this.idAssignment = idAssignment;
    }
    public Site getSite() {
        return action.getSite();
    }
    
    public TreeSet<User> getTeam() {
        if (team==null){
            team = new TreeSet<User>();
        }
        return team;
    }
    public void setTeam(TreeSet<User> staff) {
        this.team = staff;
    }
    public void addUser(User user){
        if (user!=null)team.add(user);
    }
    public void removeUser(User user){
        if (user!=null)team.remove(user);
    }
    public TreeSet<Zone> getZones() {
        if (zones==null){
            zones = new TreeSet<Zone>();
        }
        return zones;
    }
    public void setZones(TreeSet<Zone> zones) {
        this.zones = zones;
    }
    public void addZone(Zone zone){
        if (zone !=null) zones.add(zone);
    }
    
    @Override
    public boolean equals(Object obj) {
        if (obj == this)	return true;
        if (!(obj instanceof Assignment)) return false;
        Assignment ass = null;
        try {
            ass = (Assignment) obj;
        } catch (Exception e) {
            return false;
        }
        if (this.idAssignment != ass.idAssignment) return false;
        return true;
    }
    
    @Override
    public String toString() {
        
        return idAssignment;
    }
    
    
    
    private static class Factory extends AbstractFactory{
        
        protected Object create(ParameterCollector param) {
            // La pol�tica de creaci� de asignacions determina que nom�s un usuari
            //amb rol "admin" pot crear noves assignacions.
            // Per defecte es permet tamb? el password de root declarat com a variable est�tica de User
            return new Assignment();
        }
    }
    public static class Inventory extends AbstractInventory{
        
        public boolean exist(final String id) throws Exception{
            
            ObjectContainer db = OCProvider.getInstance();
            ObjectSet<Assignment> assigns = db.query(new Predicate<Assignment>() {
                
                
                public boolean match(Assignment candidate) {
                    return candidate.idAssignment.equals(id);
                }
            });
            
            if (assigns.hasNext()){
                return true;
            } else {
                return false;
            }
        }
        
        public Assignment getNewObject(ParameterCollector param) throws Exception{
            // Delega en la factoria corresponent la creaci� d'una nova assignaci� en
            // el cas que aquesta no existeixi
            
            
            
            String newId= (String) param.get("id");
            
            if (!exist(newId)){
                //Delega en la factoria la creaci�
                param.put("factoryid", "Assignment");
                
                return (Assignment) Assignment.Factory.createObject(param);
            }else {
                
                return (Assignment) getObject(param);
            }
            
            
        }
        
        public KeyObject getNewKey(ParameterCollector param) {
            return null;
            
        }
        
        
        public Object getObject(ParameterCollector param) {
            //Carrega el Site amb el corresponent siteid
            final String key = (String) param.get("id");
            ObjectContainer db = OCProvider.getInstance();
            
            ObjectSet <Assignment> assigns = db.query(new Predicate <Assignment>() {
                public boolean match(Assignment anass) {
                    return (anass.getIdAssignment().equals(key));
                }
            });
            
            if (assigns.hasNext()){
                return assigns.next();
            } else throw new RuntimeException("Assignaci� inexistent");
        }
        public static List<Assignment> getList() {
            
            ObjectContainer db = OCProvider.getInstance();
            List<Assignment> list = db.query(Assignment.class);
            
            return list;
            
        }
        
        public static List<Assignment> getList(final Site site) {
            ObjectContainer db = OCProvider.getInstance();
            List<Assignment> list = db.query(new Predicate<Assignment>(){
                
                @Override
                public boolean match(Assignment assign) {
                    
                    return assign.getSite()==site;
                }});
                
                return list;
        }
        
        public static List<Assignment> getList(final Action action) {
            ObjectContainer db = OCProvider.getInstance();
            List<Assignment> list = db.query(new Predicate<Assignment>(){
                
                @Override
                public boolean match(Assignment assign) {
                    
                    return assign.getAction()==action;
                }});
                
                return list;
        }
        
        public static List<Assignment> getList(final User user) {
            ObjectContainer db = OCProvider.getInstance();
            List<Assignment> list = db.query(new Predicate<Assignment>(){
                
                @Override
                public boolean match(Assignment assign) {
                    
                    return assign.getTeam().contains(user);
                }});
                
                return list;
        }
        
        public static List<Assignment> getList(final Zone zone) {
            ObjectContainer db = OCProvider.getInstance();
            List<Assignment> list = db.query(new Predicate<Assignment>(){
                
                @Override
                public boolean match(Assignment assign) {
                    
                    return assign.getZones().contains(zone);
                }});
                
                return list;
        }
        
        
    }
    
    
    
    public int compareTo(Object obj) {
        return this.toString().compareTo(obj.toString());
    }
    
}
